import UtilFuncs from '../common/tools/utilfuncs.js'
var funcs = UtilFuncs.UtilFuncs;

import GlobalConst from '../common/globalConst.js'
var global = GlobalConst.GlobalConst;
import LGXCOM from '../common/common.js'

import {LGXEnums}  from '../common/sysenum.js';



var PolyposGraphSnapSvc = {}



PolyposGraphSnapSvc.absorb = function (pCurentGraph, pDataMng, mousePoint) {

    let position = pCurentGraph.getPosCopy();
    if (position.posType != LGXEnums.LGXPosMode.multiPt_Mode) {
        return false;
    }

    let posList = position.posList;
    let curentPosIdx = posList.length - 1;
    let curentPt = posList[curentPosIdx];
    if (curentPosIdx < 1) {
        return false;
    }
    let prePt = posList[curentPosIdx - 1];

    let scaling = pDataMng.getScaling();
    let lineseclenth = funcs.distancePoint(prePt, mousePoint, scaling);
    if (lineseclenth < global.MinSelRectGap) {
        return false;
    }

    let hornVertKind = funcs.chkHornVertKind(prePt, curentPt);
    if (hornVertKind == 1 || hornVertKind == 2) {
        //绘制过程中已经是横平或竖直的线则不需要再处理与其他线段的正交或平行吸附
        return false;
    }
    let absorbFlag = false;
    if (curentPosIdx > 1) {
        let prePrePt = posList[curentPosIdx - 2];
        absorbFlag = this.absorbVertical2PreLineSec(prePt, prePrePt, prePt, mousePoint, pDataMng);
        if (!absorbFlag) {
            //与自身相邻线段不垂直，则检查与自身其他线段是否平行，只有四个及以上坐标点的图形才需要做此吸附检测
            if (posList.length > 3) {
                absorbFlag = this.absorbParallel2SelfOtherLineSec(pCurentGraph, posList, curentPosIdx, mousePoint, pDataMng);
            }
            absorbFlag = this.absorbParallel2OtherLineSec(pCurentGraph, prePt, pDataMng, mousePoint);
        }
        //当前绘制线段走向确定后，再尽量跟本线路其他已有线段的长度保持一致
        this.snap2MakeSameLenthWithPreLineSec(prePt, prePrePt, mousePoint);
    }
    else {
        let curentPrePt = { x: prePt.x, y: prePt.y };
        let prePrePt = null;
        if (prePrePt) {
            absorbFlag = this.absorbVertical2PreLineSec(prePt, prePrePt, curentPrePt, mousePoint, pDataMng);
        }
        if (!absorbFlag) {
            absorbFlag = this.absorbParallel2OtherLineSec(pCurentGraph, prePt, pDataMng, mousePoint);
        }
    }
    return absorbFlag;
}


PolyposGraphSnapSvc.chkSnap2DestGraph = function (pCurentGraph, curentPrePt, mousePoint, interPtInfo, pDataMng) {
    if (pCurentGraph.m_graphType != LGXEnums.LGXGraphType.LineGraph_type
        && pCurentGraph.m_graphType != LGXEnums.LGXGraphType.Auxline_type) {
        return false;
    }
    let dstGraph = interPtInfo.graph;
    if (dstGraph.m_graphType != LGXEnums.LGXGraphType.CircleGraph_type
        && dstGraph.m_graphType != LGXEnums.LGXGraphType.ArcGraph_type) {
        //暂时只处理线与圆、圆弧相切吸附检测
        return false;
    }

    let absorbFlag = false; 
    let dstPosition = dstGraph.getPosCopy();
    let cnt = dstPosition.getCnt();
    if (pCurentGraph.m_graphType == LGXEnums.LGXGraphType.LineGraph_type) {
        if (dstGraph.m_graphType == LGXEnums.LGXGraphType.ArcGraph_type) {
            if (funcs.chkPtInArcSec(dstPosition, curentPrePt)) {
                absorbFlag = this.chkSnap2Tangency(cnt,curentPrePt, mousePoint, pDataMng);
            }
        }
        else if (dstGraph.m_graphType == LGXEnums.LGXGraphType.CircleGraph_type) {
            absorbFlag = this.chkSnap2Tangency(cnt,curentPrePt, mousePoint, pDataMng);
        }
    }

    return absorbFlag;
}

PolyposGraphSnapSvc.chkSnap2Tangency = function (cnt,curentPrePt, mousePoint, pDataMng) {
    let absorbFlag = false;
    let auxDataMng = pDataMng.getAuxDataManager();
    let preVector = funcs.getVector(cnt, curentPrePt);
    let curentVector = funcs.getVector(curentPrePt, mousePoint);
    let includeAngle = preVector.angleToAnotherVector_Degree(curentVector);
    if (Math.abs(includeAngle - 90) < global.CmpDegreeGap) {
        absorbFlag = true;
        let absorbRst = this.getPreVectorRotAngle(curentVector, preVector);
        let nextVector = absorbRst.nextVector;
        let curentLineSecLenth = funcs.distancePoint(curentPrePt, mousePoint, 1);
        let absorbX = curentPrePt.x + curentLineSecLenth * nextVector.m;
        let absorbY = curentPrePt.y + curentLineSecLenth * nextVector.n;
        mousePoint.x = absorbX;
        mousePoint.y = absorbY;
        auxDataMng.setVerticalLine(curentPrePt, cnt, curentPrePt, mousePoint, 1);
    }
    else {
        auxDataMng.setVerticalLine(curentPrePt, cnt, curentPrePt, mousePoint, 0);
    }
    return absorbFlag;
}

PolyposGraphSnapSvc.getGraphPrePt = function (graph, point) {
    if (graph.getPosType() != LGXEnums.LGXPosMode.multiPt_Mode) {
        return null;
    }
    let destPoint = null;
    if (graph.m_graphType == LGXEnums.LGXGraphType.Auxline_type) {
        let vector = graph.getRayLineVector();
        let x = point.x + vector.m;
        let y = point.y + vector.n;
        destPoint = { x, y };
    }
    else {
        let position = graph.getPosCopy();
        let p0 = position.posList[0];
        for (let i = 1; i < position.posList.length; i++) {
            let p1 = position.posList[i];
            if (funcs.chkPointOnLineSec(point, p0, p1)) {
                let dis1 = funcs.distancePoint(point, p0, 1);
                let dis2 = funcs.distancePoint(point, p1, 1);
                destPoint = p0;
                if (dis2 > dis1) {
                    destPoint = p1;
                }
                break;
            }
        }
    }
    return destPoint;
}

//当前绘制线段走向确定后，再尽量跟本线路其他已有线段的长度保持一致
PolyposGraphSnapSvc.snap2MakeSameLenthWithPreLineSec = function (prePt, prePrePt, mousePoint) {
    let preLen = funcs.distancePoint(prePt, prePrePt, 1);
    let curentLen = funcs.distancePoint(prePt, mousePoint, 1);
    console.log("preLen:" + preLen + "   curentLen:" + curentLen);
    if (Math.abs(preLen - curentLen) > global.MinSelRectGap * 4) {
        return false;
    }
    let vector = funcs.getVector(prePt, mousePoint);
    let absorbX = prePt.x + preLen * vector.m;
    let absorbY = prePt.y + preLen * vector.n;
    mousePoint.x = absorbX;
    mousePoint.y = absorbY;
    return true;
}

//与自身其他线段平行
PolyposGraphSnapSvc.absorbParallel2SelfOtherLineSec = function (pCurentGraph, posList, curentPosIdx, mousePoint, pDataMng) {
    let curentPt = posList[curentPosIdx];
    if (curentPosIdx < 1) {
        return false;
    }
    let preIdx = curentPosIdx - 1;
    let prePt = posList[preIdx];

    let curentVector = new LGXCOM.LGXVector();
    curentVector.setBy2Pt(prePt, mousePoint);

    let paralelLineSec = new LGXCOM.LGXLineSection();
    let dstVector = null;
    let parallelFlag = false;
    let nextVector = new LGXCOM.LGXVector();
    let p0 = posList[0];
    let chkPreIdx = 0;
    for (let i = 1; i < posList.length; i++) {
        let nxtPt = posList[i];
        if (i == curentPosIdx || i == preIdx
            || chkPreIdx == curentPosIdx || chkPreIdx == preIdx) {
            chkPreIdx = i;
            p0 = posList[i];
            continue;
        }
        chkPreIdx = i;
        nextVector.setBy2Pt(p0, nxtPt);

        paralelLineSec.stPt.clone(p0);
        paralelLineSec.endPt.clone(nxtPt);

        p0 = posList[i];
        let includeAngle = nextVector.angleToAnotherVector_Degree(curentVector);
        console.log("includeAngle:" + includeAngle);
        if (Math.abs(includeAngle) < global.CmpDegreeGap) {
            parallelFlag = true;
            dstVector = nextVector;
            break;
        }
    }

    if (!parallelFlag && pCurentGraph.m_graphType == LGXEnums.LGXGraphType.PolygonGraph_type) {
        //如果是封闭连接线或多边形，则需要比较末尾和起始点间的线段
        let nxtPt = posList[0];
        if (0 != curentPosIdx && 0 != preIdx
            && chkPreIdx != curentPosIdx && chkPreIdx != preIdx) {
            nextVector.setBy2Pt(p0, nxtPt);
            let includeAngle = nextVector.angleToAnotherVector_Degree(curentVector);
            if (Math.abs(includeAngle) < global.CmpDegreeGap) {
                parallelFlag = true;
                dstVector = nextVector;
                paralelLineSec.stPt.clone(p0);
                paralelLineSec.endPt.clone(nxtPt);
            }
        }
    }

    if (parallelFlag && dstVector) {
        //当前线段与目标线段接近平行，则判断目标线段的走向是跟当前一致还是相反
        //求目标线段向量与当前向量的叉积
        let crossDotAngle1 = dstVector.angleByCrossMultiply2Another(curentVector);
        let crossDotAngle2 = curentVector.angleByCrossMultiply2Another(dstVector);
        if (crossDotAngle1 > 90 && crossDotAngle2 > 90) {
            //大于90°则走向相反，需要反转
            let tempVector = dstVector.cloneCopy();
            tempVector.invert();
            dstVector = tempVector;
        }

        let curentLineSecLenth = funcs.distancePoint(prePt, mousePoint, 1);
        let absorbX = prePt.x + curentLineSecLenth * dstVector.m;
        let absorbY = prePt.y + curentLineSecLenth * dstVector.n;
        mousePoint.x = absorbX;
        mousePoint.y = absorbY;

        pDataMng.getAuxDataManager().setParallelLine(paralelLineSec.stPt, paralelLineSec.endPt, prePt, mousePoint, 1);
    }
    else {
        pDataMng.getAuxDataManager().setParallelLine(paralelLineSec.stPt, paralelLineSec.endPt, prePt, mousePoint, 0);
    }
    return parallelFlag;
}

PolyposGraphSnapSvc.absorbVertical2PreLineSec = function (prePt, prePrePt, curentPrePt, mousePoint, pDataMng) {
    let absorbFlag = false;
    let curentVector = new LGXCOM.LGXVector();
    curentVector.setBy2Pt(curentPrePt, mousePoint);

    let preVector = new LGXCOM.LGXVector();
    preVector.setBy2Pt(prePrePt, prePt);

    let includeAngle = curentVector.angleToAnotherVector_Degree(preVector);
    if (Math.abs(includeAngle - 90) < global.CmpDegreeGap) {
        absorbFlag = true;
        let absorbRst = this.getPreVectorRotAngle(curentVector, preVector);
        let nextVector = absorbRst.nextVector;
        let curentLineSecLenth = funcs.distancePoint(curentPrePt, mousePoint, 1);
        let absorbX = curentPrePt.x + curentLineSecLenth * nextVector.m;
        let absorbY = curentPrePt.y + curentLineSecLenth * nextVector.n;
        mousePoint.x = absorbX;
        mousePoint.y = absorbY;
        pDataMng.getAuxDataManager().setVerticalLine(prePt, prePrePt, curentPrePt, mousePoint, 1);
        pDataMng.getAuxDataManager().setInterLine(prePt, prePrePt, curentPrePt, mousePoint, 0);
    }
    else {
        pDataMng.getAuxDataManager().setVerticalLine(prePt, prePrePt, curentPrePt, mousePoint, 0);
        absorbFlag = this.autoSnap2SpecialAngle(prePt, prePrePt, curentPrePt, mousePoint);
        pDataMng.getAuxDataManager().setInterLine(prePt, prePrePt, curentPrePt, mousePoint, 1);
    }
    return absorbFlag;
}

PolyposGraphSnapSvc.autoSnap2SpecialAngle = function (prePt, prePrePt, curentPrePt, mousePoint) {
    let absorbFlag = false;
    let curentVector = new LGXCOM.LGXVector();
    curentVector.setBy2Pt(curentPrePt, mousePoint);

    let preVector = new LGXCOM.LGXVector();
    preVector.setBy2Pt(prePt, prePrePt);

    let rotaAngle = preVector.angleByCrossMultiply2Another(curentVector);
    let rst = this.chkClose2SpecialAngle(rotaAngle);
    if (rst.flag) {
        absorbFlag = true;
        let close2Vector = preVector.rotateCopy(rst.destAngle);
        let curentLineSecLenth = funcs.distancePoint(curentPrePt, mousePoint, 1);
        let absorbX = curentPrePt.x + curentLineSecLenth * close2Vector.m;
        let absorbY = curentPrePt.y + curentLineSecLenth * close2Vector.n;
        mousePoint.x = absorbX;
        mousePoint.y = absorbY;
    }
    return absorbFlag;
}

PolyposGraphSnapSvc.chkClose2SpecialAngle = function (rotaAngle) {
    const arr = [0, 30, 45, 60, 90, 120, 135, 180, 210, 225, 240, 270, 300, 315, 360];
    let flag = false;
    let destAngle = 0;
    for (let i = 0; i < arr.length; i++) {
        let t = arr[i];
        if (Math.abs(rotaAngle - t) < global.CmpDegreeGap) {
            flag = true;
            destAngle = t;
            break;
        }
    }
    return { flag, destAngle };
}

//对可能垂直的两个向量，以preVector为基准，求curentVector变成真正与preVector垂直后正式向量值
//以及preVector到目的垂直向量的旋转角度
PolyposGraphSnapSvc.getPreVectorRotAngle = function (curentVector, preVector) {
    let invertPreVector = preVector.cloneCopy();
    let preVct2CurentVectAngle = invertPreVector.angleByCrossMultiply2Another(curentVector);
    let vectorRotAngle = 0;
    if (Math.abs(preVct2CurentVectAngle - 90) < global.CmpDegreeGap) {
        vectorRotAngle = 90;
    }
    else if (Math.abs(preVct2CurentVectAngle - 270) < global.CmpDegreeGap) {
        vectorRotAngle = 270;
    }
    else if (Math.abs(preVct2CurentVectAngle + 90) < global.CmpDegreeGap) {
        vectorRotAngle = -90;
    }
    else if (Math.abs(preVct2CurentVectAngle + 270) < global.CmpDegreeGap) {
        vectorRotAngle = -270;
    }
    let nextVector = invertPreVector.cloneCopy();
    nextVector.rotate(vectorRotAngle);
    return { vectorRotAngle, nextVector };
}



PolyposGraphSnapSvc.absorbParallel2OtherLineSec = function (pCurentGraph, prePt, pDataMng, mousePoint) {
    let absorbFlag = false;
    let curentVector = new LGXCOM.LGXVector();
    curentVector.setBy2Pt(prePt, mousePoint);
    let tAllGraphLst = pDataMng.getAllGraphs();
    for (let i = 0; i < tAllGraphLst.length; i++) {
        let dstGraph = tAllGraphLst[i];
        if (dstGraph.getPos().posType != LGXEnums.LGXPosMode.multiPt_Mode) {
            continue;
        }
        if (dstGraph.getUseful() != 1 || pCurentGraph == dstGraph) {
            continue;
        }
        absorbFlag = this.absorbParallel2OtherGraphLineSec(dstGraph, prePt, curentVector, mousePoint, pDataMng);
        if (absorbFlag) {
            break;
        }
    }
    return absorbFlag;
}

//与自身其他线段平行
PolyposGraphSnapSvc.absorbParallel2OtherGraphLineSec = function (pDstGraph, stPt, curentVector, mousePoint, pDataMng) {
    let posList = pDstGraph.getPos().posList;
    let length = posList.length;
    if (length < 2) {
        return false;
    }

    let dstVector = null;
    let parallelFlag = false;
    let nextVector = new LGXCOM.LGXVector();
    let paralelLineSec = new LGXCOM.LGXLineSection();
    let prePt = posList[0];
    let preIdx = 0;
    for (let i = 1; i < posList.length; i++) {
        let nxtPt = posList[i];
        nextVector.setBy2Pt(prePt, nxtPt);
        let includeAngle = nextVector.angleToAnotherVector_Degree(curentVector);
        console.log("includeAngle:" + includeAngle);
        if (Math.abs(includeAngle) < global.CmpDegreeGap) {
            parallelFlag = true;
            dstVector = nextVector;
            paralelLineSec.stPt.clone(prePt);
            paralelLineSec.endPt.clone(nxtPt);
            break;
        }
        prePt = posList[i];
        preIdx = i;
    }

    if (!parallelFlag && pDstGraph.m_graphType == LGXEnums.LGXGraphType.PolygonGraph_type) {
        //如果是封闭连接线或多边形，则需要比较末尾和起始点间的线段
        let nxtPt = posList[0];
        nextVector.setBy2Pt(prePt, nxtPt);
        let includeAngle = nextVector.angleToAnotherVector_Degree(curentVector);
        if (Math.abs(includeAngle) < global.CmpDegreeGap) {
            parallelFlag = true;
            dstVector = nextVector;
            paralelLineSec.stPt.clone(prePt);
            paralelLineSec.endPt.clone(nxtPt);
        }
    }

    if (parallelFlag && dstVector) {
        //当前线段与目标线段接近平行，则判断目标线段的走向是跟当前一致还是相反
        //求目标线段向量与当前向量的叉积
        console.log("dstVector:");
        console.log(dstVector);
        console.log("curentVector:");
        console.log(curentVector);
        let crossDotAngle1 = curentVector.angleByCrossMultiply2Another(dstVector);
        let crossDotAngle2 = dstVector.angleByCrossMultiply2Another(curentVector);
        console.log("invertdstVector:" + crossDotAngle1 + "  " + crossDotAngle2);
        if (crossDotAngle1 > 90 && crossDotAngle2 > 90) {
            //大于90°则走向相反，需要反转
            let tempVector = dstVector.cloneCopy();
            tempVector.invert();
            dstVector = tempVector;
            console.log("invertdstVector:" + crossDotAngle1 + "  " + crossDotAngle2);
            console.log(dstVector);
        }

        let curentLineSecLenth = funcs.distancePoint(stPt, mousePoint, 1);
        let absorbX = stPt.x + curentLineSecLenth * dstVector.m;
        let absorbY = stPt.y + curentLineSecLenth * dstVector.n;
        mousePoint.x = absorbX;
        mousePoint.y = absorbY;

        pDataMng.getAuxDataManager().setParallelLine(paralelLineSec.stPt, paralelLineSec.endPt, stPt, mousePoint, 1);
    }
    else {
        pDataMng.getAuxDataManager().setParallelLine(paralelLineSec.stPt, paralelLineSec.endPt, stPt, mousePoint, 0);
    }
    return parallelFlag;
}


export default { PolyposGraphSnapSvc }


